﻿using System.Linq;
using Common.Commands;
using Common.Commands.MemberCommands;
using Core.Domain.Model;
using Core.Infrastructure.CustomExceptions;
using Sanelib.Common.Helpers;
using Sanelib.DataOperation;
using Sanelib.Dto;

namespace Core.Processors.MemberProcessors
{
    public class UpdateMemberProcessor : ICommandProcessor<UpdateMember>
    {
        private const string UserWithSameUsernameExceptionMssg =
         "A user with the same username already exists in the system.";

        private const string UserWithSameEmailExceptionMssg =
            "A user with the same email address already exists in the system.";

        private readonly IRepository<Member> _memberRepository;

        public UpdateMemberProcessor(IRepository<Member> memberRepository)
        {
            _memberRepository = memberRepository;
        }

        public dynamic Process(UpdateMember command)
        {
            EnsureNameUniqueness(command);
            EnsureEmailUniqueness(command);

            var response = new WebApiResultResponse();
            var member = _memberRepository.GetById(command.Id);

            member.Name = command.Name;
            member.DateOfBirth = command.DateOfBirth;
            member.Address = command.Address;
            member.Email = command.Email;
            member.Mobile = command.Mobile;
            member.ValidFrom = command.ValidFrom;
            member.ValidTo = command.ValidTo;
            member.SendSms = command.SendSms;
            member.SendEmail = command.SendEmail;
            member.UsePrint = command.UsePrint;
            member.Block = command.Block;
            member.Role = command.Role;
            member.UserStatus = command.UserStatus;
            member.ImageData = command.ImageData;
            member.ModifiedBy = command.UserId;

            _memberRepository.Update(member);

            response.IsSuccess = false;
            return response;
        }

        private void EnsureNameUniqueness(UpdateMember command)
        {
            var userWithSameUsername = _memberRepository.GetAllFor(Property.Of<Member>(entity => entity.Name), command.Name).SingleOrDefault();

            if (userWithSameUsername == null || userWithSameUsername.Id == command.Id) return;
            throw new DomainProcessException(UserWithSameUsernameExceptionMssg);
        }

        private void EnsureEmailUniqueness(UpdateMember command)
        {
            var userWithSameEmail = _memberRepository.GetAllFor(Property.Of<Member>(entity => entity.Email), command.Email).SingleOrDefault();

            if (userWithSameEmail == null || userWithSameEmail.Id == command.Id) return;
            throw new DomainProcessException(UserWithSameEmailExceptionMssg);
        }
    }
}